Pass the layout signal via GdkSurface to GtkRoot
authorJonas Ådahl <jadahl@gmail.com>
Tue, 24 Nov 2020 21:02:53 +0000 (22:02 +0100)
committerJonas Ådahl <jadahl@gmail.com>
Mon, 7 Dec 2020 08:46:39 +0000 (09:46 +0100)
Don't have GtkRoot listen directly to the layout signal on the frame
clock, but let it pass through GdkSurface. This will allow GdkSurface to
be more involved in the layout phase.

gdk/gdksurface.c
gdk/gdksurface.h
gtk/gtkroot.c
gtk/gtkwidget.c
gtk/gtkwidgetprivate.h

index f5f4a5790dc7f51e8eb7235bd42be3fa33f1da3f..226a7c7e534060ab12b1dd6611a54ae2308a56b8 100644 (file)
@@ -1370,6 +1370,45 @@ gdk_surface_process_updates_internal (GdkSurface *surface)
   g_object_unref (surface);
 }
 
+static void
+gdk_surface_layout_on_clock (GdkFrameClock *clock,
+                             void          *data)
+{
+  GdkSurface *surface = GDK_SURFACE (data);
+
+  g_return_if_fail (GDK_IS_SURFACE (surface));
+
+  if (GDK_SURFACE_DESTROYED (surface))
+    return;
+
+  if (!GDK_SURFACE_IS_MAPPED (surface))
+    return;
+
+  if (surface->update_freeze_count)
+    return;
+
+  g_signal_emit (surface, signals[LAYOUT], 0, surface->width, surface->height);
+}
+
+void
+gdk_surface_request_layout (GdkSurface *surface)
+{
+  GdkFrameClock *frame_clock;
+
+  if (surface->update_freeze_count ||
+      gdk_surface_is_toplevel_frozen (surface))
+    {
+      surface->pending_phases |= GDK_FRAME_CLOCK_PHASE_LAYOUT;
+      return;
+    }
+
+  frame_clock = gdk_surface_get_frame_clock (surface);
+  g_return_if_fail (frame_clock);
+
+  gdk_frame_clock_request_phase (frame_clock,
+                                 GDK_FRAME_CLOCK_PHASE_LAYOUT);
+}
+
 static void
 gdk_surface_paint_on_clock (GdkFrameClock *clock,
                             void          *data)
@@ -2451,6 +2490,10 @@ gdk_surface_set_frame_clock (GdkSurface     *surface,
                         "resume-events",
                         G_CALLBACK (gdk_surface_resume_events),
                         surface);
+      g_signal_connect (G_OBJECT (clock),
+                        "layout",
+                        G_CALLBACK (gdk_surface_layout_on_clock),
+                        surface);
       g_signal_connect (G_OBJECT (clock),
                         "paint",
                         G_CALLBACK (gdk_surface_paint_on_clock),
@@ -2471,6 +2514,9 @@ gdk_surface_set_frame_clock (GdkSurface     *surface,
       g_signal_handlers_disconnect_by_func (G_OBJECT (surface->frame_clock),
                                             G_CALLBACK (gdk_surface_resume_events),
                                             surface);
+      g_signal_handlers_disconnect_by_func (G_OBJECT (surface->frame_clock),
+                                            G_CALLBACK (gdk_surface_layout_on_clock),
+                                            surface);
       g_signal_handlers_disconnect_by_func (G_OBJECT (surface->frame_clock),
                                             G_CALLBACK (gdk_surface_paint_on_clock),
                                             surface);
index 6b2cfcd03bc7c230477d26f0aa66745cee22acc1..4c47fe659ba762dd94778e1d8306b7a2843b67ad 100644 (file)
@@ -118,6 +118,9 @@ void          gdk_surface_beep            (GdkSurface       *surface);
 GDK_AVAILABLE_IN_ALL
 void       gdk_surface_queue_render       (GdkSurface       *surface);
 
+GDK_AVAILABLE_IN_ALL
+void       gdk_surface_request_layout     (GdkSurface       *surface);
+
 GDK_AVAILABLE_IN_ALL
 GdkFrameClock* gdk_surface_get_frame_clock      (GdkSurface     *surface);
 
index a480173695fe33e4b93055371c72aaecd170d872..6bdf1b74a199f20436ab98d71b6f50c358e1e303 100644 (file)
@@ -195,8 +195,10 @@ gtk_root_after_update_cb (GdkFrameClock *clock,
 }
 
 static void
-gtk_root_layout_cb (GdkFrameClock *clock,
-                    GtkRoot       *self)
+gtk_root_layout_cb (GdkSurface *surface,
+                    int         width,
+                    int         height,
+                    GtkRoot    *self)
 {
   GtkWidget *widget = GTK_WIDGET (self);
 
@@ -231,19 +233,22 @@ gtk_root_layout_cb (GdkFrameClock *clock,
 
   if (gtk_root_needs_layout (self))
     {
-      gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_UPDATE);
-      gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_LAYOUT);
+      gdk_frame_clock_request_phase (gdk_surface_get_frame_clock (surface),
+                                     GDK_FRAME_CLOCK_PHASE_UPDATE);
+      gdk_surface_request_layout (surface);
     }
 }
 
 void
 gtk_root_start_layout (GtkRoot *self)
 {
+  GdkSurface *surface;
   GdkFrameClock *clock;
 
   if (!gtk_root_needs_layout (self))
     return;
 
+  surface = gtk_widget_get_surface (GTK_WIDGET (self));
   clock = gtk_widget_get_frame_clock (GTK_WIDGET (self));
   if (clock == NULL)
     return;
@@ -260,19 +265,20 @@ gtk_root_start_layout (GtkRoot *self)
                           GINT_TO_POINTER (after_update_handler));
 
       layout_handler =
-        g_signal_connect (clock, "layout",
+        g_signal_connect (surface, "layout",
                           G_CALLBACK (gtk_root_layout_cb), self);
       g_object_set_qdata (G_OBJECT (self), quark_layout_handler,
                           GINT_TO_POINTER (layout_handler));
     }
 
   gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_UPDATE);
-  gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_LAYOUT);
+  gdk_surface_request_layout (surface);
 }
 
 void
 gtk_root_stop_layout (GtkRoot *self)
 {
+  GdkSurface *surface;
   GdkFrameClock *clock;
   guint layout_handler;
   guint after_update_handler;
@@ -287,8 +293,9 @@ gtk_root_stop_layout (GtkRoot *self)
   if (layout_handler == 0)
     return;
 
+  surface = gtk_widget_get_surface (GTK_WIDGET (self));
   clock = gtk_widget_get_frame_clock (GTK_WIDGET (self));
-  g_signal_handler_disconnect (clock, layout_handler);
+  g_signal_handler_disconnect (surface, layout_handler);
   g_signal_handler_disconnect (clock, after_update_handler);
   g_object_set_qdata (G_OBJECT (self), quark_layout_handler, NULL);
   g_object_set_qdata (G_OBJECT (self), quark_after_update_handler, NULL);
index ab9de00cd23d4a4cbb89496f122fc94e37e491ed..6d1e3c865dc501e672967cfc481508df775e7975 100644 (file)
@@ -3244,7 +3244,7 @@ gtk_widget_remove_surface_transform_changed_callback (GtkWidget *widget,
     }
 }
 
-static GdkSurface *
+GdkSurface *
 gtk_widget_get_surface (GtkWidget *widget)
 {
   GtkNative *native = gtk_widget_get_native (widget);
index a79ee938da9e1a3a3d2f84367ba148f69777debf..667df882ce5a345ced2c382df07adb361dda6b59 100644 (file)
@@ -228,6 +228,8 @@ void         gtk_widget_ensure_resize       (GtkWidget *widget);
 void         gtk_widget_ensure_allocate     (GtkWidget *widget);
 void          _gtk_widget_scale_changed     (GtkWidget *widget);
 
+GdkSurface * gtk_widget_get_surface         (GtkWidget *widget);
+
 void         gtk_widget_render              (GtkWidget            *widget,
                                              GdkSurface           *surface,
                                              const cairo_region_t *region);